package pl.edu.agh.nn.neuron;

import java.util.ArrayList;
import java.util.List;

import pl.edu.agh.nn.functions.IActivationFunction;

public abstract class AbstractNeuron<T extends AbstractSynapse> implements IOutputProducer {

	protected IActivationFunction activation;
	protected double bias = 0.0;
	protected double output;
	protected List<T> synapses;

	public AbstractNeuron() {
	}

	public AbstractNeuron(IActivationFunction activation, List<T> synapses, double bias) {
		this.activation = activation;
		this.synapses = synapses;
		this.bias = bias;
	}

	@Override
	public double getOutput() {
		return output;
	}

	protected double gatherInput() {
		double ret = 0.0f;
		for (T i : synapses) {
			ret += i.getWeight() * i.getFrom().getOutput();
		}
		return ret;
	}

	public void computeOutput() {
		output = activation.compute(gatherInput() + bias);
	}

	public void createSynapses(List<? extends AbstractNeuron<?>> list) {
		List<T> synapses = new ArrayList<T>();
		for (AbstractNeuron<?> neuron : list) {
			synapses.add(createSynapse(neuron));
		}
		this.synapses = synapses;
	}

	public IActivationFunction getActivation() {
		return activation;
	}

	public double getBias() {
		return bias;
	}

	public List<T> getSynapses() {
		return synapses;
	}

	public void setActivation(IActivationFunction activation) {
		this.activation = activation;
	}

	public void setBias(double bias) {
		this.bias = bias;
	}

	public void setOutput(double output) {
		this.output = output;
	}

	public void setSynapses(List<T> synapses) {
		this.synapses = synapses;
	}

	protected abstract T createSynapse(AbstractNeuron<?> neuron);

}
